'''生成token'''
from wtforms import ValidationError

from app.libs.error_code import AuthFailed, ParameterException
from app.libs.redprint import Redprint
from flask import  current_app, jsonify
from app.models.user import User
from app.validators.forms import ClientForm, UserEmailForm, TokenForm, LoginGetTokenForm
from app.libs.enums import ClientTypeEnum
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer,BadSignature,SignatureExpired
api = Redprint('token')

@api.route('/secret', methods=['POST'])
def get_token_info():
    form=TokenForm().validate_for_api()
    s = Serializer(current_app.config['SECRET_KEY'])
    try:
        data=s.loads(form.token.data,return_header=True)
    except SignatureExpired:
        raise AuthFailed('token is expired',error_code=1003)
    except BadSignature:
        raise AuthFailed('token is invalid',error_code=1002)
    r={
        'scope':data[0]['scope'],
        'create_at':data[1]['iat'], #令牌创建时间 调试看看
        'expire_in':data[1]['exp'], #有限期
        'uid':data[0]['uid']
    }
    return jsonify(r)

@api.route('', methods=['POST'])
def get_token():
    form = LoginGetTokenForm().validate_for_api()
    user=User.query.filter_by(email=form.account.data).first()
    if not user.check_password(form.secret.data):
        return ParameterException(msg='密码错误')
    promise = {
        ClientTypeEnum.USER_EMAIL: User.verify,
    }
    identity = promise[ClientTypeEnum(form.type.data)](
        form.account.data,
        form.secret.data
    )
    expiration = current_app.config['TOKEN_EXPIRATION']
    token = generate_auth_token(identity['uid'],
                                form.type.data,
                                identity['scope'],
                                expiration
                                )
    t = {'token': token.decode('ascii')}
    return jsonify(t), 201
    # token


def generate_auth_token(uid, ac_type, scope=None, expiration=60):
    '''生成令牌'''
    s = Serializer(current_app.config['SECRET_KEY'], expires_in=expiration)
    return s.dumps({
        'uid': uid,
        'type': ac_type.value,
        'scope': scope
    })

